package com.blueocean_health.care.management.service.order_service_info;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import com.blueocean_health.care.management.domain.base.OrderInfo;
import com.blueocean_health.care.management.domain.base.ReceiptDetail;
import com.blueocean_health.care.management.domain.dto.BuildDeptFloolDto;
import com.blueocean_health.care.management.em.*;
import com.blueocean_health.care.management.mapper.OrderInfoMapper;
import com.blueocean_health.care.management.service.DeptBuildFloorService;
import com.blueocean_health.care.management.util.Arith;
import jdk.nashorn.internal.ir.ReturnNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.blueocean_health.care.management.common.base.em.TimeType;
import com.blueocean_health.care.management.common.base.id.IdUtils;
import com.blueocean_health.care.management.common.base.string.StringUtils;
import com.blueocean_health.care.management.common.base.time.TimeUtils;
import com.blueocean_health.care.management.domain.base.OrderServiceInfo;
import com.blueocean_health.care.management.domain.base.OrderServiceNurseInfo;
import com.blueocean_health.care.management.domain.ordervo.ChargeInfo;
import com.blueocean_health.care.management.domain.ordervo.OrderDetail;
import com.blueocean_health.care.management.domain.ordervo.OrderInfoVo;
import com.blueocean_health.care.management.domain.ordervo.SickRoomInfo;
import com.blueocean_health.care.management.domain.ordervo.UserOrderVo;
import com.blueocean_health.care.management.domain.ordervo.WorkerInfo;
import com.blueocean_health.care.management.domain.ordervo.WorkerVo;
import com.blueocean_health.care.management.exception.OrderServiceException;
import com.blueocean_health.care.management.mapper.OrderServiceInfoMapper;
import com.blueocean_health.care.management.mapper.OrderServiceNurseInfoMapper;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单服务信息
 * @author meisanfeng
 */
@Service
public class OrderServiceInfoServiceImpl implements OrderServiceInfoService {
	
	@Autowired
	private OrderServiceInfoMapper orderServiceInfoMapper;

    @Autowired
    private OrderInfoMapper orderInfoMapper;
	
	@Autowired
	private OrderServiceNurseInfoMapper orderServiceNurseInfoMapper;

	@Autowired
	private DeptBuildFloorService deptBuildFloorService;

	
	/**
	 * 新增加一个订单服务信息
	 */
    @Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateOrderServiceInfo(OrderInfoVo order,String orderType,Integer userId,String hid) throws OrderServiceException {
		//收据信息
		ReceiptDetail receiptDetail = new ReceiptDetail();
		if (order.getMoneyStatus()){
			receiptDetail = order.getReceiptDetail();
		}

		Integer outworker = null;
		if (receiptDetail.getUserId()!=null){
			outworker = Integer.parseInt(receiptDetail.getUserId());
		}else{
			outworker = userId;
		}


		String orderId = order.getOrderId();
    	List<OrderDetail> orderDetails = order.getOrderDetail();
    	if(orderDetails == null || orderDetails.size() == 0){//如果没有订单明细
    		if(!StringUtils.isEmpty(orderId)){
    			deleteOrder(orderId);
    		}
    		return ;
    	}
    	//计算所有的订单明细中的时间是否出现交叉
    	boolean conflictFlag = false;
		List<OrderDetail> orderDetailsHaveFlag = new ArrayList<>();
		//给每个明细一个唯一标识
		for (int i = 0; i < orderDetails.size(); i++) {
			OrderDetail thisDetail = orderDetails.get(i);
			thisDetail.setDetailFlag(i);
			orderDetailsHaveFlag.add(thisDetail);
		}
		//用每个明细的结束时间与其他明细的时间段进行比较
		for (int i = 0; i < orderDetailsHaveFlag.size(); i++){
			OrderDetail thisDetail = orderDetailsHaveFlag.get(i);

			for (int j = 0; j < orderDetailsHaveFlag.size(); j++){
				OrderDetail otherDetail = orderDetailsHaveFlag.get(j);
				if (!otherDetail.getDetailFlag().equals(thisDetail.getDetailFlag())){
					Date param = thisDetail.getEndTime();
					Date beginTime = otherDetail.getBeginTime();
					Date endTime = otherDetail.getEndTime();
					conflictFlag = TimeUtils.compare(param,beginTime,endTime);
					if (conflictFlag){
						throw new OrderServiceException("订单明细中出现了时间交叉");
					}
				}
			}
		}

		//校验每个订单明细的小时制是否一致
        Integer timeType = orderDetails.get(0).getTimeType();
        for (int i = 0; i < orderDetails.size(); i++) {
            OrderDetail thisDetail = orderDetails.get(i);
            if (!timeType.equals(thisDetail.getTimeType())){
                throw new OrderServiceException("所有订单明细的时间类型必须一致");
            }
        }

    	for (OrderDetail detail : orderDetails) {

            //小时制类型
            final Integer serviceType = detail.getTimeType();

            //护工信息
			WorkerInfo workerInfo = detail.getWorkerInfo();
			//护工集合
			List<WorkerVo> workers = workerInfo.getWorkers();
    		
    		//订单明细
    		OrderServiceInfo orderServiceInfo = new OrderServiceInfo();
    		//订单号
    		orderServiceInfo.setOrderId(orderId);
    		//服务ID号
    		orderServiceInfo.setServiceId(IdUtils.getRandomIdByDateTime());
    		//开始时间
    		orderServiceInfo.setBeginTime(detail.getBeginTime());
    		//结束时间
    		orderServiceInfo.setEndTime(detail.getEndTime());
    		//外勤姓名
			//订单拆分后改为收据信息里面的签单人id
			orderServiceInfo.setOutworker(outworker);
			//备注
    		orderServiceInfo.setRemark(detail.getRemark());
    		//收费信息
    		ChargeInfo chargeInfo = detail.getChargeInfo();
    		//病情级别
    		orderServiceInfo.setIllnessGrade(chargeInfo.getDiseaseGrade());
    		//服务天数
    		orderServiceInfo.setDay(chargeInfo.getDay());
    		//单日价格
    		orderServiceInfo.setOneDayPrice(chargeInfo.getOneDayPrice() == null ? 0 : chargeInfo.getOneDayPrice().doubleValue());
    		//总费用
    		orderServiceInfo.setTotalPrice(chargeInfo.getTotalPrice() == null ? 0 : chargeInfo.getTotalPrice().doubleValue());
    		//优惠后总价
    		orderServiceInfo.setActualTotalPrice(chargeInfo.getActualTotalPrice() == null ? 0 : chargeInfo.getActualTotalPrice().doubleValue());

            //天数小时数
            String[] split = orderServiceInfo.getDay().split("\\.");
            Double hoursType = 0.0;
            if (serviceType.equals(OrderTimeTypeEnum._1.getKey())){
                hoursType = 24.0;
            }else {
                hoursType = 12.0;
            }
			//新入和续费 实际日单价和小时单价
			if (!OrderTypeEnum._3.getKey().equals(orderType)){
				//如果是整天的时候，算一下实际日单价，如果不是整天，直接存前端给的值
				if ("0".equals(split[1])){
					Double day = Double.parseDouble(split[0]);
					Double totalPrice = chargeInfo.getActualTotalPrice() == null ? 0 : chargeInfo.getActualTotalPrice().doubleValue();
					Double actualDayPrice = totalPrice/day;
					BigDecimal b = new BigDecimal(actualDayPrice);
					actualDayPrice = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
					orderServiceInfo.setActualDayPrice(actualDayPrice);
				}else {
					orderServiceInfo.setActualDayPrice(chargeInfo.getOneDayPrice() == null ? 0 : chargeInfo.getOneDayPrice().doubleValue());
				}
				//小时价格
				orderServiceInfo.setOneHourPrice(chargeInfo.getHourPrice() == null ? 0 : chargeInfo.getHourPrice().doubleValue());
			}else {
				//退款单实际日服务费和小时服务费计算
                //数据库中存储的实际日费用和实际小时费用,
                Double day = Double.parseDouble(split[0]);
                Double hours = Double.parseDouble(split[1]);
                Double totalHours = day * hoursType + hours;
                Double totalPrice = chargeInfo.getActualTotalPrice() == null ? 0 : chargeInfo.getActualTotalPrice().doubleValue();
                //二对一的订单要用总费用除以2
                if(detail.getWorkerInfo().getServiceType().equals(ServiceTypeEnum._2.getKey())){
                    totalPrice = Arith.div(totalPrice,2,2);
                }
                //实际小时费用=退费金额/所有小时数（整天转换为12小时或24小时）；
                Double hoursPrice = Arith.div( totalPrice,totalHours);
                //实际日费用=退费金额/所有小时数*24（或者12）
                Double dayPrice = Arith.mul(hoursPrice,hoursType);

                BigDecimal dbig = new BigDecimal(dayPrice);
                dbig.setScale(2,BigDecimal.ROUND_HALF_UP);

                orderServiceInfo.setActualDayPrice(dbig.doubleValue());
                //小时费用直接存前端的值
                orderServiceInfo.setOneHourPrice(chargeInfo.getHourPrice().doubleValue());
			}

    		
    		//病房信息
    		SickRoomInfo sickRoomInfo = detail.getSickRoomInfo();
    		//科室ID
			if (StringUtils.isEmpty(sickRoomInfo.getDepartment())){
				throw new OrderServiceException("请完善订单明细-科室信息");
			}
    		orderServiceInfo.setDepartment(Integer.parseInt(sickRoomInfo.getDepartment()));
    		//楼号
    		orderServiceInfo.setBuildingNumber(Integer.parseInt(sickRoomInfo.getBuildingNumber()));
    		//楼层
    		orderServiceInfo.setFloor(Integer.parseInt(sickRoomInfo.getFloor()));
    		//病房号
    		orderServiceInfo.setHospitalBed(sickRoomInfo.getBedNumber());
    		//责任护士
    		orderServiceInfo.setNurse(sickRoomInfo.getNurse());
    		//责任护士长
    		orderServiceInfo.setHeadNurse(sickRoomInfo.getHeadNurse());
    		//version
    		orderServiceInfo.setVersion(order.getVersion());
    		//创建时间
    		orderServiceInfo.setCreateTime(new Date());
    		
    		//标识订单是否有护工详情
    		orderServiceInfo.setStflag(workers.size() == 0? "0":"1");
    		//标识订单是否为取消状态
    		orderServiceInfo.setCancel("0");
			//订单类型
			orderServiceInfo.setOrderType(orderType);
    		//明细退款标识
            if (OrderTypeEnum._3.getKey().equals(orderType)){
                orderServiceInfo.setServiceRefundFlag(null);
                //所退明细id （退款单有值）
                orderServiceInfo.setRefundServiceId(order.getServiceOrderId());
            }else {
                orderServiceInfo.setServiceRefundFlag(ServiceRefundEnum._1.getKey());
				orderServiceInfo.setRefundServiceId(null);
            }

			//订单小时制类型
			orderServiceInfo.setOrderTypeFlag(serviceType);
            //单项服务id
			if (!StringUtils.isEmpty(workerInfo.getSingleService())){
                orderServiceInfo.setSingleService(Integer.parseInt(workerInfo.getSingleService()));
            }

            //新增字段 serviceType  医院id
            orderServiceInfo.setServiceType(detail.getWorkerInfo().getServiceType());
			orderServiceInfo.setHospitalId(hid);

			//新增字段 附加费
            Double additionalPrice = detail.getChargeInfo().getAdditionalPrice() == null? 0.0 :detail.getChargeInfo().getAdditionalPrice().doubleValue();
			if (StringUtils.isEmpty(additionalPrice) || additionalPrice < 0){
				throw new OrderServiceException("附加费不可为空或负数");
			}else{
				if (OrderTypeEnum._3.getKey().equals(orderType)){
					//进行退费时，退费的附加费金额不允许超过原订单的附加费金额
					OrderServiceInfo refundOrderService = orderServiceInfoMapper.getOrderServiceInfoByServiceId(order.getServiceOrderId());

					if (additionalPrice > refundOrderService.getActualTotalPrice().doubleValue()){
						throw new OrderServiceException("退费的附加费金额不允许超过原订单的附加费金额");
					}else {
						orderServiceInfo.setAdditionalPrice(additionalPrice);
					}
				}else {
					orderServiceInfo.setAdditionalPrice(additionalPrice);
				}
			}

			//是否有附加费  1有 0 无
			orderServiceInfo.setHasAdditionalPrice(detail.getChargeInfo().getHasAdditionalPrice());

    		//数据入库
    		int count = orderServiceInfoMapper.insert(orderServiceInfo);
    		if(count > 0){
    			
    		}else{
    			throw new OrderServiceException("订单服务信息入库异常");
    		}
		
    		{
    			for (WorkerVo workerVo : workers) {
    				//护工详细信息
					OrderServiceNurseInfo nurseInfo = new OrderServiceNurseInfo();
					nurseInfo.setServNurseId(IdUtils.getRandomIdByDateTime());
					//订单编号
					nurseInfo.setOrderId(orderId);
					//服务编号
					nurseInfo.setServiceId(orderServiceInfo.getServiceId());
					//开始时间
					nurseInfo.setStartTime(orderServiceInfo.getBeginTime());
					//结束时间
					nurseInfo.setEndTime(orderServiceInfo.getEndTime());
					//服务天数
					nurseInfo.setServiceDay(orderServiceInfo.getDay());
					//实际天数
					nurseInfo.setFinallyDay(orderServiceInfo.getDay());
					//服务类型
					nurseInfo.setServiceType(workerInfo.getServiceType());
					//护工ID
					nurseInfo.setWorkerId(workerVo.getWorkerId());
					//总工资
					nurseInfo.setTotalPay(workerVo.getTotalPay().doubleValue());


					//新入和续费订单的日工资和小时工资计算
                    if (!OrderTypeEnum._3.getKey().equals(orderType)){
                        //平均日工资
                        //如果是整天的时候，前端的总工资是可以编辑的，所以要用总工资/服务天数
                        //不是整天的时候，前端不可以编辑，还用前端给的
                        if ("0".equals(split[1])){
                            Double day = Double.parseDouble(split[0]);
                            Double totalpay = workerVo.getTotalPay().doubleValue();
                            Double onedaypay = totalpay/day;
                            BigDecimal b = new BigDecimal(onedaypay);
                            onedaypay = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            nurseInfo.setOneDayPay(onedaypay);
                        }else {
                            nurseInfo.setOneDayPay(workerVo.getDayPay().doubleValue());
                        }
                        //小时工资
                        nurseInfo.setOneHourPay(workerVo.getHourPay().doubleValue());
                    }else{
                        //退费时，数据库中存储的实际日护理费和实际小时护理费,
                        Double day = Double.parseDouble(split[0]);
                        Double hours = Double.parseDouble(split[1]);
                        Double totalHours = day * hoursType + hours;

                        // 实际小时护理费=扣除/所有小时数（整天转换为12小时或24小时）；
                        Double hoursPrice = Arith.div( workerVo.getTotalPay().doubleValue(),totalHours);
                        // 实际日护理费=扣除金额/所有小时数*24（或者12）
                        Double dayPrice =  Arith.mul(hoursPrice,hoursType);
                        BigDecimal b = new BigDecimal(dayPrice);
                        b.setScale(2,BigDecimal.ROUND_HALF_UP);

                        nurseInfo.setOneDayPay(b.doubleValue());

						BigDecimal hb = new BigDecimal(hoursPrice);
						hb.setScale(2,BigDecimal.ROUND_HALF_UP);
                        nurseInfo.setOneHourPay(hb.doubleValue());
                    }


                    //前端输入的值，用于回显
					nurseInfo.setOneDayPayDisplay(workerVo.getDayPay().doubleValue());
					//version
					nurseInfo.setVersion(orderServiceInfo.getVersion());
					//创建时间
					nurseInfo.setCreateTime(orderServiceInfo.getCreateTime());
					//标识护工信息是否被取消了
					nurseInfo.setCancel("0");
                    //订单类型
					nurseInfo.setOrderType(orderType);
					//所退明细id （退款单有值）
					if (OrderTypeEnum._3.getKey().equals(orderType)){
						nurseInfo.setRefundServiceId(order.getServiceOrderId());
					}else {
						nurseInfo.setRefundServiceId(null);
					}

					//小时制类型
					nurseInfo.setOrderTypeFlag(serviceType);
					nurseInfo.setHospitalId(hid);

					int nurseCount = orderServiceNurseInfoMapper.insert(nurseInfo);

					if(nurseCount > 0){
					    //删除订单所有老version数据，物理删除
		    			orderInfoMapper.deleteOldVersionOrderByOrderId(order.getOrderId(),order.getVersion());
		    			orderServiceInfoMapper.deleteOldVersionOrderServiceByOrderId(order.getOrderId(),order.getVersion());
		    			orderServiceNurseInfoMapper.deleteOldVersionOrderServiceNurseByOrderId(order.getOrderId(),order.getVersion());

		    		}else{
		    			throw new OrderServiceException("订单服务信息中护工信息入库异常");
		    		}
				}
    		}
		}
    	
    }
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void deleteOrder(String orderId) throws OrderServiceException {
		orderServiceInfoMapper.deleteOrder(orderId);
		orderServiceNurseInfoMapper.deleteOrder(orderId);
	}

@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void updateOrderUserServiceInfo(UserOrderVo orderInfo, String orderId) throws OrderServiceException {
		//订单明细
		OrderServiceInfo orderServiceInfo = new OrderServiceInfo();
		//订单号
		orderServiceInfo.setOrderId(orderId);
		//服务ID号
		String serviceId = IdUtils.getRandomIdByDateTime();
		orderServiceInfo.setServiceId(serviceId);
		//开始时间
		orderServiceInfo.setBeginTime(orderInfo.getBeginTime());
		//用户端订单结束时间也填开始时间
		orderServiceInfo.setEndTime(orderInfo.getBeginTime());
		//备注
		//orderServiceInfo.setRemark(orderInfo.getPatientRemark());


		//如果有具体地址字段，说明是在院外，则存入外派科室的相关数据
		if (StringUtils.isEmpty(orderInfo.getPatientAddress())){
			//科室ID
			if (!StringUtils.isEmpty(orderInfo.getDepartment())) {
				orderServiceInfo.setDepartment(Integer.parseInt(orderInfo.getDepartment()));
			}
			//楼号
			if (!StringUtils.isEmpty(orderInfo.getBuildingNumber())) {
				orderServiceInfo.setBuildingNumber(Integer.parseInt(orderInfo.getBuildingNumber()));
			}
			//楼层
			if (!StringUtils.isEmpty(orderInfo.getFloor())) {
				orderServiceInfo.setFloor(Integer.parseInt(orderInfo.getFloor()));
			}
			//病房号
			if (!StringUtils.isEmpty(orderInfo.getBedNumber())) {
				orderServiceInfo.setHospitalBed(orderInfo.getBedNumber());
			}
		}else {
			BuildDeptFloolDto buildDeptFloolDto =  deptBuildFloorService.getWaiPaiInfo(orderInfo.getHospital());
			orderServiceInfo.setDepartment(Integer.parseInt(buildDeptFloolDto.getDeptId()));
			orderServiceInfo.setBuildingNumber(Integer.parseInt(buildDeptFloolDto.getBuildId()));
			orderServiceInfo.setFloor(Integer.parseInt(buildDeptFloolDto.getFloorId()));
		}

		//version
		orderServiceInfo.setVersion(orderInfo.getVersion());
		//创建时间
		orderServiceInfo.setCreateTime(new Date());
		
		//标识订单是否有护工详情
		orderServiceInfo.setStflag("0");
		//标识订单是否为取消状态
		orderServiceInfo.setCancel("0");

		//订单拆分后新加的字段
		//0：:24小时制   1:12小时制
		orderServiceInfo.setOrderTypeFlag(1);
		orderServiceInfo.setServiceRefundFlag(ServiceRefundEnum._1.getKey());
		orderServiceInfo.setOrderType(OrderTypeEnum._1.getKey());

		//数据入库
		int count = orderServiceInfoMapper.insert(orderServiceInfo);
		if(count > 0){
            OrderServiceNurseInfo osn = new OrderServiceNurseInfo();
            osn.setServNurseId(IdUtils.getRandomIdByDateTime());
            osn.setOrderId(orderId);
            osn.setServiceId(serviceId);

            osn.setStartTime(orderInfo.getBeginTime());
            //用户端订单结束时间也填开始时间
            osn.setEndTime(orderInfo.getBeginTime());
            osn.setServiceType(orderInfo.getServiceType());
            osn.setVersion(orderInfo.getVersion());

            osn.setCreateTime(new Date());
            osn.setCancel("0");

            //订单拆分后新增字段
            osn.setOrderTypeFlag(1);
            osn.setOrderType(OrderTypeEnum._1.getKey());

            int inflag = orderServiceNurseInfoMapper.insert(osn);
            if (inflag < 1){
                throw new OrderServiceException("订单护工信息入库异常");
            }

            //二对一的时候加两条
		    if (ServiceTypeEnum._2.getKey().equals(orderInfo.getServiceType())){
                osn.setServNurseId(IdUtils.getRandomIdByDateTime());
                osn.setId(null);
                int addflag = orderServiceNurseInfoMapper.insert(osn);
                if (addflag < 1){
                    throw new OrderServiceException("订单护工信息入库异常");
                }
            }
		}else{
			throw new OrderServiceException("订单服务信息入库异常");
		}
	}

}
